home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_05 / 1005059a < prev    next >
Text File  |  1992-03-18  |  5KB  |  233 lines

  1. /* Listing 2 */
  2.  
  3. /*****************************************************
  4.     ADCDMA.C 
  5.  
  6.     Routines for Data acquisition through DMA on the
  7.     Lab Master AD.
  8.  
  9.     Copyright Don Bradley, 1991.
  10.  
  11.     Permission is granted for used of these routines
  12.     in any manner as long as this copyright notice is
  13.     included.
  14.  
  15.     Tested using Quick C 2.5 and MSC 6.0 on a 
  16.     Toshiba T5200.
  17.  
  18.  *****************************************************/
  19.  
  20. #include <io.h>
  21. #include <errno.h>
  22. #include <conio.h>
  23.  
  24. #include "dma.h"
  25. #include "labmastr.h"
  26.  
  27. // DMA buffer
  28. static int far *dma_buffer;
  29.  
  30. // DMA buffer index
  31. static unsigned int dma_buff_index;
  32. // previous DMA buffer index
  33. static unsigned int old_dma_buff_index;
  34.  
  35. // number of conversions to collect
  36. static long num_to_collect;
  37. // number of conversions collected
  38. static long num_collected;
  39.  
  40. // DMA finished flag
  41. static int dma_finished;
  42. // DMA channel number
  43. static int dma_chn;
  44.  
  45. void (*process)(int);
  46.  
  47. /*****************************************************
  48.     init_adc_dma is a routine used for dma controlled 
  49.     analogue voltage input.
  50.  
  51.     called by:
  52.  
  53.     init_adc_dma(num_chn, num_samples, *freq, dma_chn,
  54.                  proc_func);
  55.  
  56.     where
  57.  
  58.         int num_chn            # of channels to sample. 
  59.                             Start channel is always 
  60.                             chn 0. Thus chans collect 
  61.                             are 0 ... num_chn-1
  62.         long num_samples    # of samples to collect. 
  63.                             A sample is the group of 
  64.                             channels
  65.         double *freq        Frequency of sampling in Hz.
  66.         int dma_chn            DMA channel number from 5-7.
  67.         void(*proc_func)(int) process function to be 
  68.                               called after each value is
  69.                               retrieved.
  70.  *****************************************************/
  71. int init_adc_dma(unsigned int num_chn, 
  72.         long num_samples, double *freq, int dma_channel,
  73.         void (*proc_func)(int))
  74. /*& Setup adc for dma transfer. */
  75.     {
  76.     long length;
  77.     unsigned int i;
  78.     unsigned int dma_mode;
  79.  
  80.     // check for proper passed values
  81.     if (dma_channel < 5 || dma_channel > 7)
  82.         return (0);
  83.  
  84.     dma_chn = dma_channel;
  85.  
  86.     disable_dma(dma_chn);
  87.     
  88.     disable_adc();
  89.  
  90.     if(num_chn > MAX_CHANNELS)
  91.         return(FALSE);
  92.     
  93.     if (*freq == 0.0)
  94.         return (FALSE);
  95.  
  96.     process = proc_func;
  97.         
  98.     /* create buffer for storing data in */
  99.     
  100.     if(!(dma_buffer = alloc_dma_buffer(dma_chn, 
  101.           ADC_DMA_BUFFER_LEN)))
  102.         return (FALSE);
  103.  
  104.     clr_adc_dma_buffer();
  105.     
  106.     // Frequency adjusted for number of channels.
  107.     // Next version will have a burst mode enabled.
  108.     *freq *= num_chn;
  109.  
  110.     *freq = timerad(*freq);
  111.  
  112.     // Readjust frequency for number of channels.
  113.     *freq /= num_chn;
  114.  
  115.  
  116.     // Setup the channel gain array.
  117.     for (i = 0;    i < num_chn;    i++) {
  118.         outp(ADC_VIRTCHAN, i);
  119.         outp(ADC_CHN_GAIN_ARRAY, 
  120.               ADC_GAIN_1 | ADC_BANK_0 | i);
  121.         }
  122.  
  123.     // set adc control register
  124.     outp(ADC_CONTROL, ADC_FIFO_ENABLE | 
  125.           ADC_SINGLE_ENDED | ((dma_chn - 4) << 2));
  126.  
  127.     outp(ADC_LASTCHAN, num_chn-1);
  128.  
  129.     // Start converstions at channel zero
  130.     outp(ADC_VIRTCHAN, 0);
  131.     
  132.     num_to_collect = num_chn * num_samples;
  133.     num_collected = 0L;
  134.  
  135.     length = (num_to_collect < (long)ADC_DMA_BUFFER_LEN) ?
  136.           num_to_collect : (long)ADC_DMA_BUFFER_LEN;
  137.  
  138.     // Setup dma transfer.
  139.     if(num_to_collect > (long)ADC_DMA_BUFFER_LEN)
  140.         dma_mode = DMA_DEMAND_MODE | DMA_ADDRESS_INC | 
  141.               DMA_CONTINUOUS_ENABLE | DMA_ADC_TRANSFER;
  142.     else
  143.         dma_mode = DMA_DEMAND_MODE | DMA_ADDRESS_INC | 
  144.               DMA_CONTINUOUS_DISABLE | DMA_ADC_TRANSFER;
  145.  
  146.     dma(dma_chn, dma_mode, dma_buffer, 
  147.           (unsigned int) length);
  148.  
  149.     dma_finished = FALSE;
  150.  
  151.     return (TRUE);
  152.     }
  153.  
  154. void get_next_adc_values()
  155. /*& Returns the pointer to the next memory location, 
  156.      increments appropriate buffer pointers. */
  157.     {
  158.  
  159.     if(dma_buffer[dma_buff_index] == NON_ADC_VALUE)
  160.         return;
  161.  
  162.     // wait until sample has been recorded
  163.     while(dma_buffer[dma_buff_index] != NON_ADC_VALUE) {
  164.  
  165.         // Check for overrun by looking at last adc 
  166.         // buffer location. If this    location has a valid
  167.         // adc value then an overrun has occurred. An 
  168.         // over run condtion will result in automatic 
  169.         // termination of adc collection. To detect an 
  170.         // overrun the number of samples collected will 
  171.         // be less than those requested.
  172.  
  173.         if(dma_buffer[old_dma_buff_index] != NON_ADC_VALUE) {
  174.             terminate_adc_dma();
  175.             return;
  176.             }
  177.  
  178.         process(dma_buffer[dma_buff_index]);
  179.  
  180.         // clear collected value from DMA buffer
  181.         dma_buffer[dma_buff_index] = NON_ADC_VALUE;
  182.  
  183.         // increment buffer pointer
  184.         old_dma_buff_index = dma_buff_index;
  185.         if (++dma_buff_index >= ADC_DMA_BUFFER_LEN)
  186.             dma_buff_index = 0;
  187.     
  188.         // Increment number of conversions collected. 
  189.         // Used in automatic termination for repetitive 
  190.         // sampling under DMA.
  191.         if(++num_collected >= num_to_collect) {
  192.             terminate_adc_dma();
  193.             return;
  194.             }
  195.         }
  196.     }
  197.  
  198. void terminate_adc_dma()
  199. /* Terminates adc dma collection. */
  200.     {
  201.     disable_dma(dma_chn);
  202.     outp(ADC_CONTROL, 0);
  203.     
  204.     free_dma_buffer(dma_chn);
  205.     
  206.     dma_finished = TRUE;
  207.     }
  208.  
  209. void clr_adc_dma_buffer()
  210. /*& Clears the adc buffer to a non possible value. */
  211. {
  212.     unsigned int i;
  213.  
  214.     for (i = 0;    i < ADC_DMA_BUFFER_LEN;    i++)
  215.         dma_buffer[i] = NON_ADC_VALUE;
  216.  
  217.     dma_buff_index = 0;
  218.     old_dma_buff_index = ADC_DMA_BUFFER_LEN-1;
  219. }
  220.  
  221. int adc_dma_done(void)
  222. /*& Returns TRUE if all conversions are done. */
  223.     {
  224.     return(dma_finished);
  225.     }
  226.  
  227. long adc_dma_conversion_count()
  228. /*& Returns the number of samples collected. */
  229.     {
  230.     return(num_collected);
  231.     }
  232.  
  233.